#include <exception>
#include <string>

struct LexicalException : public std::exception {
    std::string msg;
    int line = 0;
    int column = 0;

    LexicalException(const std::string& m, int l = 0, int c = 0)
        : msg(m), line(l), column(c) {}

    const char* what() const noexcept override {
        return msg.c_str();
    }
};

struct SyntaxException : public std::exception {
    std::string msg;
    int line = 0;
    int column = 0;

    SyntaxException(const std::string& m, int l = 0, int c = 0)
        : msg(m), line(l), column(c) {}

    const char* what() const noexcept override {
        return msg.c_str();
    }
};

struct SemanticException : public std::exception {
    std::string msg;
    int line = 0;
    int column = 0;

    SemanticException(const std::string& m, int l = 0, int c = 0)
        : msg(m), line(l), column(c) {}

    const char* what() const noexcept override {
        return msg.c_str();
    }
};
